/*
 *  testClassArrayMap.cpp
 *  kangmodb
 *
 *  Created by 강모 김 on 11. 5. 8..
 *  Copyright 2011 강모소프트. All rights reserved.
 *
 */

#include "gtest/gtest.h"

#include "testCommon.h"
#include "types.h"
#include "kdInfra.h"
#include "table.h"	
#include "arrayMap.h"	
	

/** @brief Test kdArrayMap class.
 */
class ArrayMapTest : public testing::Test {
protected:  // You should make the members protected s.t. they can be
	// accessed from sub-classes.
	
	// virtual void SetUp() will be called before each test is run.  You
	// should define it if you need to initialize the varaibles.
	// Otherwise, this can be skipped.
	virtual void SetUp() {
	}
	
	// virtual void TearDown() will be called after each test is run.
	// You should define it if there is cleanup work to do.  Otherwise,
	// you don't have to provide it.
	//
	virtual void TearDown() {
	}
protected:
	stgTable * table_;
};



/** @brief Basic tests for ArrayMap.
 */
TEST_F(ArrayMapTest, Basic_GetKeysAssigned) {
	kdArrayMap<stgTableId, stgTable*> map;
	
	ASSERT_TRUE( map.initialize(3 /* max size */ ) == 0 );
	stgTable * table;
	stgTableId tableId;
	
	// TODO : Hit Assertion : put key 0.
#define PSEUDO_TBL_ADDR(n) ((stgTable*)(n*8))
	// Put 1st table
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(1), &tableId) == 0);
	ASSERT_TRUE( tableId == 1);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(1) );

	// Put 2nd table
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(2), &tableId) == 0);
	ASSERT_TRUE( tableId == 2);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(1) );
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(2) );

	// Put 3rd table
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(3), &tableId) == 0);
	ASSERT_TRUE( tableId == 3);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(1) );
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(2) );
	ASSERT_TRUE( map.get(3, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(3) );

	// Put 4th table => ArrayMap FULL.
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(4), &tableId) == KD_EXCP_ARRAY_MAP_FULL);
	
	// Remove the 2nd mapping
	ASSERT_TRUE( map.remove(2) == 0);
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == NULL );
	
	// Put 4th table
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(4), &tableId) == 0);
	// The removed tableId is reused.
	ASSERT_TRUE( tableId == 2);
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(4) );

	// Remove tableID 1, 3
	ASSERT_TRUE( map.remove(1) == 0);
	ASSERT_TRUE( map.remove(3) == 0);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == NULL );
	ASSERT_TRUE( map.get(3, &table) == 0); ASSERT_TRUE( table == NULL );

	// Put 5th, 6th table, the table Id 1 and 3 are reused.
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(5), &tableId) == 0);
	ASSERT_TRUE( tableId == 1);
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(6), &tableId) == 0);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(5) );
	ASSERT_TRUE( tableId == 3);
	ASSERT_TRUE( map.get(3, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(6) );

	ASSERT_TRUE( map.destroy() == 0 );
}


/** @brief Basic tests for ArrayMap.
 */
TEST_F(ArrayMapTest, Basic_SetKey) {
	kdArrayMap<stgTableId, stgTable*> map;
	
	ASSERT_TRUE( map.initialize(3 /* max size */ ) == 0 );
	stgTable * table;
	stgTableId tableId;
	
	// TODO : Hit Assertion : put key 0.
#define PSEUDO_TBL_ADDR(n) ((stgTable*)(n*8))
	// Put 1st table
	ASSERT_TRUE( map.put(1, PSEUDO_TBL_ADDR(1)) == 0);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(1) );

	// Put 2nd table
	ASSERT_TRUE( map.put(2, PSEUDO_TBL_ADDR(2)) == 0);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(1) );
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(2) );

	// Put 3rd table
	ASSERT_TRUE( map.put(3, PSEUDO_TBL_ADDR(3)) == 0);
	ASSERT_TRUE( map.get(1, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(1) );
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(2) );
	ASSERT_TRUE( map.get(3, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(3) );

	// Put 4th table => ArrayMap FULL.
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(4), &tableId) == KD_EXCP_ARRAY_MAP_FULL);

	// Remove the 2nd mapping
	ASSERT_TRUE( map.remove(2) == 0);
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == NULL );
	
	// Put 4th table
	ASSERT_TRUE( map.put(PSEUDO_TBL_ADDR(4), &tableId) == 0);
	// The removed tableId is reused.
	ASSERT_TRUE( tableId == 2);
	ASSERT_TRUE( map.get(2, &table) == 0); ASSERT_TRUE( table == PSEUDO_TBL_ADDR(4) );
	
	ASSERT_TRUE( map.destroy() == 0 );
}

